package cloud.maque.sso.server.controller;

import cloud.maque.auth.model.BaseUserModel;
import cloud.maque.sso.server.service.UserHandle;
import cn.dev33.satoken.context.SaHolder;
import cn.dev33.satoken.oauth2.SaOAuth2Manager;
import cn.dev33.satoken.oauth2.config.SaOAuth2ServerConfig;
import cn.dev33.satoken.oauth2.processor.SaOAuth2ServerProcessor;
import cn.dev33.satoken.oauth2.strategy.SaOAuth2Strategy;
import cn.dev33.satoken.oauth2.template.SaOAuth2Util;
import cn.dev33.satoken.stp.StpUtil;
import cn.dev33.satoken.util.SaFoxUtil;
import cn.dev33.satoken.util.SaResult;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;


/**
 * Sa-Token OAuth2 Server端 控制器
 */
@RestController
public class SaOAuth2ServerController {


    @Autowired
    UserHandle userHandle;

    // OAuth2-Server 端：处理所有 OAuth2 相关请求
    @RequestMapping("/oauth2/*")
    public Object request() {
        System.out.println("------- 进入请求: " + SaHolder.getRequest().getUrl());
        Object result = SaOAuth2ServerProcessor.instance.dister();
        return result;
    }

    @RequestMapping("/oauth2/userinfo")
    public SaResult GetUserInfo() {

        // 获取 Access-Token 对应的账号id
        String accessToken = SaOAuth2Manager.getDataResolver().readAccessToken(SaHolder.getRequest());
        Object loginId = SaOAuth2Util.getLoginIdByAccessToken(accessToken);
        System.out.println("-------- 此Access-Token对应的账号id: " + loginId);

        // 校验 Access-Token 是否具有权限: userinfo
        SaOAuth2Util.checkAccessTokenScope(accessToken, "userinfo");
        BaseUserModel userModel = userHandle.getUserInfo(loginId.toString());
        return SaResult.ok().setData(userModel);
    }

    // Sa-Token OAuth2 定制化配置
    @Autowired
    public void configOAuth2Server(SaOAuth2ServerConfig oauth2Server) {

        // 添加 client 信息
        //https://sa-token.cc/doc.html#/oauth2/oauth2-data-loader?id=oauth2-%e8%87%aa%e5%ae%9a%e4%b9%89%e6%95%b0%e6%8d%ae%e5%8a%a0%e8%bd%bd%e5%99%a8
//        oauth2Server.addClient(
//                new SaClientModel()
//                        .setClientId("1001")    // client id
//                        .setClientSecret("aaaa-bbbb-cccc-dddd-eeee")    // client 秘钥
//                        .addAllowRedirectUris("*")    // 所有允许授权的 url
//                        .addContractScopes("openid", "userid", "userinfo")    // 所有签约的权限
//                        .addAllowGrantTypes(     // 所有允许的授权模式
//                                GrantType.authorization_code, // 授权码式
//                                GrantType.implicit,  // 隐式式
//                                GrantType.refresh_token,  // 刷新令牌
//                                GrantType.password,  // 密码式
//                                GrantType.client_credentials,  // 客户端模式
//                                "third_oauth2"
//                        )
//        );

        // 可以添加更多 client 信息，只要保持 clientId 唯一就行了
        // oauth2Server.addClient(...)


        // 重写 AccessToken 创建策略，返回会话令牌 JWT格式
        SaOAuth2Strategy.instance.createAccessToken = (clientId, loginId, scopes) -> {
            System.out.println("----返回会话令牌");
            return StpUtil.getOrCreateLoginSession(loginId);
        };

        // 配置：未登录时返回的View
        oauth2Server.notLoginView = () -> {
            String msg = "当前会话在OAuth-Server端尚未登录，请先访问"
                    + "<a href='/oauth2/doLogin?name=sa&pwd=123456' target='_blank'> doLogin登录 </a>"
                    + "进行登录之后，刷新页面开始授权";
            return msg;
        };

        // 配置：登录处理函数
        oauth2Server.doLoginHandle = (name, pwd) -> {
            return userHandle.login(name, pwd);
        };

        // 配置：确认授权时返回的 view
        oauth2Server.confirmView = (clientId, scopes) -> {
            String scopeStr = SaFoxUtil.convertListToString(scopes);
            String yesCode =
                    "fetch('/oauth2/doConfirm?client_id=" + clientId + "&scope=" + scopeStr + "', {method: 'POST'})" +
                            ".then(res => res.json())" +
                            ".then(res => location.reload())";
            String res = "<p>应用 " + clientId + " 请求授权：" + scopeStr + "，是否同意？</p>"
                    + "<p>" +
                    "        <button onclick=\"" + yesCode + "\">同意</button>" +
                    "        <button onclick='history.back()'>拒绝</button>" +
                    "</p>";
            return res;
        };
    }

}
